#ifndef _PSO_H_
#define _PSO_H_

#include "params.h"
#include "particle.h"
#include "position.h"
#include "logger.h"
#include <vector>


class Pso
{
  public:
    Pso(Params *p_params, bool p_log_stats = true);
    ~Pso();
    // Run the PSO with the default parameters, return best solution 
    // ... found.
    double exec();
    // Run the PSO with a specific set of alphas; return best solution.
    double exec(double p_alpha_1, double p_alpha_2);
    double execOmega(double p_omega_1, double p_omega_2);
    // Get the parameters set for this PSO.
    const Params *getParams();

  private:
    Params *m_params;
    std::vector<Particle *> m_particles;
    Particle *m_best_overall_solution;
    double m_current_omega;
    Logger m_logger;
    bool m_log_stats;

    // Run the actual PSO. Return best solution found.
    double run();
    // Calculate initial variables of the swarm.
    void initSwarm();
    // Destroy the created particles.
    void destroySwarm();
    // Update velocity of specified particle.
    void updateVelocity(unsigned int p_particle_i);
    // Update a particles' position given its current velocity.
    void updatePosition(unsigned int p_particle_i);
    // Examine the swarm to see if a better solution has been found.
    void updateOverallBest(bool first_update = false);
    // Calculate neighbourhood's best position.
    const Position *getBestNeighbourPosition(unsigned int p_particle_i);
    // Log related functions.
    void openLogs();
    void closeLogs();
    void collectStats(unsigned int p_iteration);
};

#endif /* _PSO_H_ */
